from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse, HttpResponse, Http404
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.contrib.auth.decorators import login_required
from django.core.files.storage import default_storage
from django.conf import settings
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
import json
import os
import mimetypes
import logging
from pathlib import Path
from typing import Dict, Any, List

from apps.core.models import UploadedFile, Template
from .serializers import FileUploadSerializer, FileListSerializer, FileInfoSerializer

logger = logging.getLogger(__name__)


class FileManagerViewSet(viewsets.ViewSet):
    """文件管理器API视图集"""
    
    permission_classes = [IsAuthenticated]
    
    @action(detail=False, methods=['post'])
    def upload_files(self, request):
        """
        上传文件API
        
        POST /api/file-manager/upload_files/
        Content-Type: multipart/form-data
        
        files: 文件列表
        file_type: 文件类型 (source/template/result)
        template_id: 关联模板ID (可选)
        """
        try:
            serializer = FileUploadSerializer(data=request.data)
            if not serializer.is_valid():
                return Response({
                    'success': False,
                    'error': '请求参数无效',
                    'details': serializer.errors
                }, status=status.HTTP_400_BAD_REQUEST)
            
            data = serializer.validated_data
            uploaded_files = request.FILES.getlist('files')
            
            if not uploaded_files:
                return Response({
                    'success': False,
                    'error': '没有选择文件'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 处理文件上传
            results = self._handle_file_uploads(
                uploaded_files, 
                data['file_type'], 
                data.get('template_id')
            )
            
            return Response({
                'success': True,
                'message': f'成功上传 {len(results["success"])} 个文件',
                'uploaded_files': results['success'],
                'failed_files': results['failed'],
                'total_uploaded': len(results['success']),
                'total_failed': len(results['failed'])
            })
            
        except Exception as e:
            logger.error(f"文件上传API失败: {str(e)}", exc_info=True)
            return Response({
                'success': False,
                'error': f'上传失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def _handle_file_uploads(self, files: List, file_type: str, template_id: int = None) -> Dict[str, List]:
        """
        处理文件上传
        
        Args:
            files: 上传的文件列表
            file_type: 文件类型
            template_id: 关联模板ID
            
        Returns:
            上传结果字典
        """
        success_files = []
        failed_files = []
        
        # 获取关联模板
        template = None
        if template_id:
            try:
                template = Template.objects.get(id=template_id)
            except Template.DoesNotExist:
                logger.warning(f"模板 {template_id} 不存在")
        
        for file in files:
            try:
                # 验证文件
                validation_result = self._validate_file(file, file_type)
                if not validation_result['valid']:
                    failed_files.append({
                        'filename': file.name,
                        'error': validation_result['error']
                    })
                    continue
                
                # 创建文件记录
                uploaded_file = UploadedFile.objects.create(
                    original_name=file.name,
                    file=file,
                    file_type=file_type,
                    template=template,
                    created_by=getattr(self, 'request', None) and self.request.user if hasattr(self, 'request') and self.request.user.is_authenticated else None
                )
                
                success_files.append({
                    'id': uploaded_file.id,
                    'filename': uploaded_file.original_name,
                    'file_type': uploaded_file.file_type,
                    'file_size': uploaded_file.file.size,
                    'uploaded_at': uploaded_file.created_at.isoformat()
                })
                
                logger.info(f"文件上传成功: {file.name}")
                
            except Exception as e:
                failed_files.append({
                    'filename': file.name,
                    'error': str(e)
                })
                logger.error(f"文件上传失败 {file.name}: {str(e)}")
        
        return {
            'success': success_files,
            'failed': failed_files
        }
    
    def _validate_file(self, file, file_type: str) -> Dict[str, Any]:
        """
        验证文件
        
        Args:
            file: 上传的文件
            file_type: 文件类型
            
        Returns:
            验证结果
        """
        # 检查文件大小
        max_size = 50 * 1024 * 1024  # 50MB
        if file.size > max_size:
            return {
                'valid': False,
                'error': f'文件大小超过限制 ({max_size / 1024 / 1024:.0f}MB)'
            }
        
        # 检查文件扩展名
        allowed_extensions = {
            'source': ['.xlsx', '.xls', '.csv', '.txt'],
            'template': ['.xlsx', '.xls'],
            'result': ['.xlsx', '.xls', '.zip']
        }
        
        file_ext = Path(file.name).suffix.lower()
        if file_ext not in allowed_extensions.get(file_type, []):
            return {
                'valid': False,
                'error': f'不支持的文件格式: {file_ext}'
            }
        
        return {'valid': True}
    
    @action(detail=False, methods=['get'])
    def list_files(self, request):
        """
        获取文件列表API
        
        GET /api/file-manager/list_files/?file_type=source&page=1&page_size=20
        """
        try:
            file_type = request.query_params.get('file_type')
            template_id = request.query_params.get('template_id')
            page = int(request.query_params.get('page', 1))
            page_size = int(request.query_params.get('page_size', 20))
            
            # 构建查询
            queryset = UploadedFile.objects.all().order_by('-created_at')
            
            if file_type:
                queryset = queryset.filter(file_type=file_type)
            
            if template_id:
                queryset = queryset.filter(template_id=template_id)
            
            # 分页
            total_count = queryset.count()
            start = (page - 1) * page_size
            end = start + page_size
            files = queryset[start:end]
            
            # 序列化数据
            serializer = FileListSerializer(files, many=True)
            
            return Response({
                'success': True,
                'files': serializer.data,
                'pagination': {
                    'page': page,
                    'page_size': page_size,
                    'total_count': total_count,
                    'total_pages': (total_count + page_size - 1) // page_size
                }
            })
            
        except Exception as e:
            return Response({
                'success': False,
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=True, methods=['get'])
    def file_info(self, request, pk=None):
        """
        获取文件详细信息API
        
        GET /api/file-manager/{file_id}/file_info/
        """
        try:
            file_obj = get_object_or_404(UploadedFile, id=pk)
            
            # 获取文件系统信息
            file_path = file_obj.file.path if file_obj.file else None
            file_info = {}
            
            if file_path and os.path.exists(file_path):
                from apps.excel_processor.processor import ExcelProcessor
                file_info = ExcelProcessor.get_file_info(file_path)
            
            serializer = FileInfoSerializer({
                'id': file_obj.id,
                'original_name': file_obj.original_name,
                'file_type': file_obj.file_type,
                'template': file_obj.template.name if file_obj.template else None,
                'uploaded_at': file_obj.created_at,
                'file_url': file_obj.file.url if file_obj.file else None,
                'file_info': file_info
            })
            
            return Response({
                'success': True,
                'file': serializer.data
            })
            
        except Exception as e:
            return Response({
                'success': False,
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=True, methods=['delete'])
    def delete_file(self, request, pk=None):
        """
        删除文件API
        
        DELETE /api/file-manager/{file_id}/delete_file/
        """
        try:
            file_obj = get_object_or_404(UploadedFile, id=pk)
            
            # 删除物理文件
            if file_obj.file and default_storage.exists(file_obj.file.name):
                default_storage.delete(file_obj.file.name)
            
            # 删除数据库记录
            filename = file_obj.original_name
            file_obj.delete()
            
            logger.info(f"文件删除成功: {filename}")
            
            return Response({
                'success': True,
                'message': f'文件 {filename} 删除成功'
            })
            
        except Exception as e:
            logger.error(f"文件删除失败: {str(e)}")
            return Response({
                'success': False,
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=True, methods=['get'])
    def download_file(self, request, pk=None):
        """
        下载文件API
        
        GET /api/file-manager/{file_id}/download_file/
        """
        try:
            file_obj = get_object_or_404(UploadedFile, id=pk)
            
            if not file_obj.file or not default_storage.exists(file_obj.file.name):
                return Response({
                    'success': False,
                    'error': '文件不存在'
                }, status=status.HTTP_404_NOT_FOUND)
            
            # 获取文件路径
            file_path = file_obj.file.path
            
            # 确定MIME类型
            content_type, _ = mimetypes.guess_type(file_path)
            if not content_type:
                content_type = 'application/octet-stream'
            
            # 读取文件内容
            with open(file_path, 'rb') as f:
                response = HttpResponse(f.read(), content_type=content_type)
                response['Content-Disposition'] = f'attachment; filename="{file_obj.original_name}"'
                return response
                
        except Exception as e:
            logger.error(f"文件下载失败: {str(e)}")
            return Response({
                'success': False,
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=False, methods=['post'])
    def batch_delete(self, request):
        """
        批量删除文件API
        
        POST /api/file-manager/batch_delete/
        {
            "file_ids": [1, 2, 3]
        }
        """
        try:
            file_ids = request.data.get('file_ids', [])
            
            if not file_ids:
                return Response({
                    'success': False,
                    'error': '没有选择要删除的文件'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 获取文件对象
            files = UploadedFile.objects.filter(id__in=file_ids)
            
            deleted_count = 0
            failed_files = []
            
            for file_obj in files:
                try:
                    # 删除物理文件
                    if file_obj.file and default_storage.exists(file_obj.file.name):
                        default_storage.delete(file_obj.file.name)
                    
                    # 删除数据库记录
                    filename = file_obj.original_name
                    file_obj.delete()
                    deleted_count += 1
                    
                except Exception as e:
                    failed_files.append({
                        'id': file_obj.id,
                        'filename': file_obj.original_name,
                        'error': str(e)
                    })
            
            return Response({
                'success': True,
                'message': f'成功删除 {deleted_count} 个文件',
                'deleted_count': deleted_count,
                'failed_files': failed_files
            })
            
        except Exception as e:
            return Response({
                'success': False,
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@login_required
@require_http_methods(["POST"])
def ajax_upload_files(request):
    """
    AJAX文件上传接口
    """
    try:
        files = request.FILES.getlist('files')
        file_type = request.POST.get('file_type', 'source')
        template_id = request.POST.get('template_id')
        
        if not files:
            return JsonResponse({
                'success': False,
                'error': '没有选择文件'
            })
        
        # 处理文件上传
        viewset = FileManagerViewSet()
        viewset.request = request  # 设置request对象以便访问用户信息
        results = viewset._handle_file_uploads(files, file_type, template_id)
        
        return JsonResponse({
            'success': True,
            'message': f'成功上传 {len(results["success"])} 个文件',
            'uploaded_files': results['success'],
            'failed_files': results['failed']
        })
        
    except Exception as e:
        logger.error(f"AJAX文件上传失败: {str(e)}", exc_info=True)
        return JsonResponse({
            'success': False,
            'error': str(e)
        })


@require_http_methods(["GET"])
def ajax_file_list(request):
    """
    AJAX获取文件列表
    """
    try:
        file_type = request.GET.get('file_type')
        template_id = request.GET.get('template_id')
        
        # 构建查询
        queryset = UploadedFile.objects.all().order_by('-created_at')
        
        if file_type:
            queryset = queryset.filter(file_type=file_type)
        
        if template_id:
            queryset = queryset.filter(template_id=template_id)
        
        # 限制返回数量
        files = queryset[:50]
        
        file_list = []
        for file_obj in files:
            file_list.append({
                'id': file_obj.id,
                'original_name': file_obj.original_name,
                'file_type': file_obj.file_type,
                'template_name': file_obj.template.name if file_obj.template else None,
                'file_size': file_obj.file.size if file_obj.file else 0,
                'uploaded_at': file_obj.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                'file_url': file_obj.file.url if file_obj.file else None
            })
        
        return JsonResponse({
            'success': True,
            'files': file_list,
            'total_count': queryset.count()
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        })


def file_manager_dashboard(request):
    """
    文件管理器仪表板
    """
    # 统计信息
    stats = {
        'total_files': UploadedFile.objects.count(),
        'source_files': UploadedFile.objects.filter(file_type='source').count(),
        'template_files': UploadedFile.objects.filter(file_type='template').count(),
        'result_files': UploadedFile.objects.filter(file_type='result').count(),
    }
    
    # 最近上传的文件
    recent_files = UploadedFile.objects.order_by('-created_at')[:10]
    
    context = {
        'stats': stats,
        'recent_files': recent_files
    }
    
    return render(request, 'file_manager/file_manager.html', context)


@require_http_methods(["GET"])
def ajax_file_stats(request):
    """
    AJAX获取文件统计信息
    """
    try:
        # 基础统计
        total_files = UploadedFile.objects.count()
        excel_files = UploadedFile.objects.filter(
            original_name__iendswith='.xlsx'
        ).count() + UploadedFile.objects.filter(
            original_name__iendswith='.xls'
        ).count()
        csv_files = UploadedFile.objects.filter(
            original_name__iendswith='.csv'
        ).count()
        
        # 计算总文件大小
        total_size = 0
        for file_obj in UploadedFile.objects.all():
            if file_obj.file:
                try:
                    total_size += file_obj.file.size
                except:
                    pass
        
        # 计算平均文件大小
        avg_size = total_size / total_files if total_files > 0 else 0
        
        stats = {
            'total_files': total_files,
            'excel_files': excel_files,
            'csv_files': csv_files,
            'total_size': total_size,
            'avg_size': avg_size
        }
        
        return JsonResponse({
            'success': True,
            'stats': stats
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        })